package com.tfjybj.itoo.teach.provider.service.impl;

import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.uuid.BaseUuidUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tfjybj.itoo.teach.entity.CourseEntity;
import com.tfjybj.itoo.teach.model.AcademyModel;
import com.tfjybj.itoo.teach.model.CourseModel;
import com.tfjybj.itoo.teach.provider.dao.CourseDao;
import com.tfjybj.itoo.teach.provider.service.AcademyService;
import com.tfjybj.itoo.teach.provider.service.CourseService;
import com.tfjybj.itoo.teach.template.CourseExportTemplate;
import lombok.extern.slf4j.Slf4j;
import org.jplus.hyberbin.excel.utils.ExcelUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.*;

import static com.tfjybj.itoo.teach.provider.until.DemoConstants.*;

/**
 * CourseService接口实现类
 * ${base}表
 *
 * @author 田成荣
 * @version 2.0.0
 * @since 2.0.0 2018-11-08 19:34:10
 */
@Service("courseService")
@Slf4j
public class CourseServiceImpl extends BaseServicePlusImpl<CourseDao, CourseEntity> implements CourseService {

    //region 模板生成
    @Resource
    private  transient CourseDao courseDao;
    @Resource
    private AcademyService academyService;
    @Resource
    private transient RedisTemplate<String, CourseExportTemplate> redisTemplate;

    @Override
    public PageInfo<CourseModel> queryByLikeName(String name, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        //返回的总集合courseModel-缺少学院名称、课程类型名称、课程类别名称、课程性质名称
        List<CourseModel> courseInfo = courseDao.queryLikeName(name);
        courseInfo = this.changeValue(courseInfo);
        return new PageInfo<>(courseInfo);
    }
    //endregion

    /* **********************************以下为非模板生成的内容********************************* */

    @Override
    public PageInfo<CourseModel> queryAllCourseInfo(Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        //返回的总集合courseModel-缺少学院名称、课程类型名称、课程类别名称、课程性质名称
        List<CourseModel> courseInfo = courseDao.queryAllCourseInfo();
        courseInfo = this.changeValue(courseInfo);

        return new PageInfo<>(courseInfo);
    }

    @Override
    public List<CourseModel> findCourseByCodeAndAcademy(String code, String academy) {
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(academy)) {
            log.warn("参数为空");
        }
        return courseDao.findCourseByCodeAndAcademy(code, academy);
    }

    @Override
    public List<CourseModel> fuzzyQueryCourse(String code, String name, String academy) {
        code = code.trim();
        name = name.trim();
        academy = academy.trim();
        return courseDao.fuzzyQueryCourse(code, name, academy);
    }

    @Override
    public PageInfo<CourseModel> pageFuzzyQueryCourse(String code, String name, String academy, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        code = code.trim();
        name = name.trim();
        academy = academy.trim();
        List<CourseModel> courseList = courseDao.fuzzyQueryCourse(code, name, academy);
        courseList = this.changeValue(courseList);
        return new PageInfo<>(courseList);
    }

    @Override
    public ItooResult fuzzyQueryCourseExport(HttpServletResponse response, String code, String name, String academy) {
        Map<Serializable, Serializable> map = new HashMap<>();
        map.put(SHEET_NAME, "课程信息");
        //要导出的字段
        map.put(COLUMNS, new String[]{"code", "name", "courseCategoryName", "courseTypeName", "courseNatureName", "academyName", "classHour", "classPoint", "score"});
        //导出表格的标题
        map.put(TITLE, "课程信息");
        map.put(NAME, "课程信息表");
        //要导出的数据
        List<CourseExportTemplate> courseTemplates = new ArrayList<>();
        List<CourseModel> courseModels = this.fuzzyQueryCourse(code, name, academy);
        courseModels = this.changeValue(courseModels);
        for (CourseModel courseModel : courseModels) {
            CourseExportTemplate courseTemplate = new CourseExportTemplate();
            BeanUtils.copyProperties(courseModel, courseTemplate);
            courseTemplates.add(courseTemplate);
        }
        //为空不进行导出
        if (courseTemplates.size() == 0) {
            return ItooResult.build(ItooResult.FAIL, "没有要导出的数据！");
        }
        map.put(DATA_LIST, (Serializable) courseTemplates);
        //导出
        try {
            ExcelUtil.exportExcel(map, response);
        } catch (Exception e) {
            log.error("导出失败,未知的异常--" + e);
            return ItooResult.build(ItooResult.FAIL, "导出信息失败！");
        }
        return ItooResult.build(ItooResult.SUCCESS, "导出信息成功！");
    }

    @Override
    public List<CourseModel> queryCourseByacademy(String academy) {

        List<CourseModel> courseList = courseDao.queryCourseByacademyOrPub(academy);
        courseList = this.changeValue(courseList);
        return courseList;
    }

    /**
     * 转换字段内容-将数字转为文字
     *
     * @param courseInfo 总集合
     * @return ocurseInfo
     * @author 张家豪
     * @since 2018.11.17 10:10
     */
    private List<CourseModel> changeValue(List<CourseModel> courseInfo) {
        //1、数字转为字符串
        //课程类别（1-理论课、2-实践课、3-理论实践课）；
        //课程类型（1-专业必修，2-公共必修，3-专业选修，4-公共选修）
        //课程性质（1-人文社科，2-艺术体育，3-自然科学）
        //1、1课程类别转换
        Map<String, String> courseCategoryMap = new HashMap<>();
        courseCategoryMap.put("1", "理论课");
        courseCategoryMap.put("2", "实践课");
        courseCategoryMap.put("3", "理论实践课");
        //1、2课程类型转换
        Map<String, String> courseTypeMap = new HashMap<>();
        courseTypeMap.put("1", "专业必修");
        courseTypeMap.put("2", "公共必修");
        courseTypeMap.put("3", "专业选修");
        courseTypeMap.put("4", "公共选修");
        //1、3课程性质转换
        Map<String, String> courseNatureMap = new HashMap<>();
        courseNatureMap.put("1", "人文社科");
        courseNatureMap.put("2", "艺术体育");
        courseNatureMap.put("3", "自然科学");

        //2、查询学院名称
        //2、1列出所需ID
        List<String> academyIds = new ArrayList<>();
        for (int i = 0; i < courseInfo.size(); i++) {
            academyIds.add(courseInfo.get(i).getAcademyId());
        }
        //2、2HashSet去重
        HashSet<String> h = new HashSet<>(academyIds);
        academyIds.clear();
        academyIds.addAll(h);

        //2、3调接口查询学院名称
        List<AcademyModel> academyList = academyService.queryInfoByAcadIdOrInstId(academyIds);

        //2、4 List转Map
        Map<String, String> academyMap = new HashMap<>();
        for (int i = 0; i < academyList.size(); i++) {
            academyMap.put(academyList.get(i).getId(), academyList.get(i).getName());
        }
        //1、4填充数据
        for (int i = 0; i < courseInfo.size(); i++) {
            String academyId = courseInfo.get(i).getAcademyId();
            if(academyId == null || academyId.isEmpty()){
                courseInfo.get(i).setAcademyName("---");
            }else {
                courseInfo.get(i).setAcademyName(academyMap.get(academyId));
            }
            //填入课程类别
            String courseCategotyId = courseInfo.get(i).getCourseCategory();
            if(courseCategotyId == null || courseCategotyId.isEmpty()){
                courseInfo.get(i).setCourseCategoryName("---");
            }else{
                courseInfo.get(i).setCourseCategoryName(courseCategoryMap.get(courseCategotyId));
            }
            //填入课程类型
            String courseTypeId = courseInfo.get(i).getCourseType();
            if(courseTypeId == null || courseTypeId.isEmpty()){
                courseInfo.get(i).setCourseTypeName("---");
            }else {
                courseInfo.get(i).setCourseTypeName(courseTypeMap.get(courseTypeId));
            }
            //填入课程性质
            String courseNatureId = courseInfo.get(i).getCourseNature();
            if(courseNatureId == null || courseNatureId.isEmpty()){
                courseInfo.get(i).setCourseNatureName("---");
            }else {
                courseInfo.get(i).setCourseNatureName(courseNatureMap.get(courseNatureId));
            }
        }
        return courseInfo;
    }

    /**
     * 根据学院ID查询非公选课
     *
     * @param academy 学院id
     * @return coursemodel
     * @author 张家豪
     * @since 2018.11.18 11:24
     */
    @Override
    public List<CourseModel> queryNonPubCourseByAcademy(String academy) {
        return courseDao.queryNonPubCourseByAcademy(academy);
    }

    /**
     * 根据学院ID查询公选课
     *
     * @param academy 学院id
     * @return coursemodel
     * @author 张家豪
     * @since 2018.11.18 11:24
     */
    @Override
    public List<CourseModel> queryPubCourseByAcademy(String academy) {
        return courseDao.queryPubCourseByAcademy(academy);
    }

    /**
     * 根据id查询课程信息，筛选非公选课
     *
     * @param ids 课程id集合
     * @return coursemodel
     * @author 张家豪
     * @since 2018.11.18 15:21
     */
    @Override
    public List<CourseModel> queryNonPubCourseByIds(List<String> ids) {
        return courseDao.queryNonPubCourseByIds(ids);
    }

    /**
     * 根据id查询课程信息，筛选公选课
     *
     * @param ids 课程id集合
     * @return coursemodel
     * @author 张家豪
     * @since 2018.11.18 15:21
     */
    @Override
    public List<CourseModel> queryPubCourseByIds(List<String> ids) {
        return courseDao.queryPubCourseByIds(ids);
    }

    /**
     * 根据id查询课程信息
     *
     * @param ids 课程id集合
     * @return coursemodel
     * @author 张家豪
     * @since 2018.11.18 15:21
     */
    @Override
    public List<CourseModel> queryCourseByIds(List<String> ids) {
        return courseDao.queryCourseByIds(ids);
    }

    /**
     * 下载模板-导入用
     *
     * @param response 响应
     * @return 下载成功或失败
     * @author 张家豪
     * @since 2018.11.21 09:39
     */
    @Override
    public Boolean downTemplate(HttpServletResponse response) {
        Map<Serializable, Serializable> map = new HashMap<>(16);
        List<CourseExportTemplate> templateList = new ArrayList<>();
        CourseExportTemplate courseExportTemplate = new CourseExportTemplate();
        courseExportTemplate.setCode("12058");
        courseExportTemplate.setName("A语言");
        courseExportTemplate.setCourseCategoryName("理论课");
        courseExportTemplate.setCourseTypeName("公共选修");
        courseExportTemplate.setCourseNatureName("人文社科");
        courseExportTemplate.setAcademyName("数学与信息科学学院");
        courseExportTemplate.setClassHour("6");
        courseExportTemplate.setClassPoint("6");
        courseExportTemplate.setScore("6");
        templateList.add(courseExportTemplate);
        //excel设置
        map.put(SHEET_NAME, "课程信息");
        map.put(COLUMNS, new String[]{"code", "name", "courseCategoryName", "courseTypeName", "courseNatureName", "academyName", "classHour", "classPoint", "score"});
        map.put(TITLE, "课程信息模板");
        map.put(NAME, "课程信息模板");
        map.put(DATA_LIST, (Serializable) templateList);

        try {
            ExcelUtil.exportExcel(map, response);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 查询所有学院数据
     *
     * @return 所有学院和机构信息
     * @author 张家豪
     * @since 2018.11.21 15:43
     */
    @Override
    public List<AcademyModel> queryProfessionOrInstitutionInfo() {
        return academyService.queryAcadOrInstInfo();
    }

    /**
     * 根据code查询课程信息-验证code是否重复
     *
     * @param code 课程代码
     * @return 课程信息
     * @author 张家豪
     * @since 2018.11.22 08:28
     */
    @Override
    public List<CourseModel> findByCode(String code) {
        return courseDao.findByCode(code);
    }

    /**
     * 根据name查询课程信息-验证name是否重复
     *
     * @param name 课程名称
     * @return 课程信息
     * @author 张家豪
     * @since 2018.11.22 08:28
     */
    @Override
    public List<CourseModel> findByName(String name) {
        return courseDao.findByName(name);
    }

    /**
     * 验证code是否存在
     *
     * @param code 课程代码
     * @return 存在或者不存在
     * @author 张家豪
     * @since 2018.11.22 08:44
     */
    @Override
    public List<CourseModel> isExistByCode(String code) {
        return courseDao.findByCode(code);
    }

    /**
     * 验证name是否存在
     *
     * @param name 课程名称
     * @return 存在或者不存在
     * @author 张家豪
     * @since 2018.11.22 08:44
     */
    @Override
    public List<CourseModel> isExistByName(String name) {
        return courseDao.findByName(name);
    }

    /**
     * 根据课程类型和所属学院查询课程信息（类型必填，学院选填）
     *
     * @param academyId  学院id
     * @param courseType 课程类型
     * @return coursemodel
     * @author 张家豪
     * @since 2018.11.22 14:51
     */
    @Override
    public List<CourseModel> queryCourseByTypeAndAcademy(List<String> courseType, String academyId) {
        return courseDao.queryCourseByTypeAndAcademy(courseType, academyId);
    }

    /**
     * 导入课程信息
     *
     * @param multipartFile 批量导入的文件
     * @param request       请求
     * @param response      响应
     * @return itooresult 批量导入的结果
     * @author 张家豪
     * @since 2018.11.25 08:38
     */
    @Override
    public ItooResult importCourse(MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("UTF-8");
        try {
            String fileName = multipartFile.getOriginalFilename();
            if (fileName == null) {
                log.error("导入失败，fileName is null");
                return ItooResult.build(ItooResult.FAIL, "传入的文件为空");
            }
            // excel解析成list
            Map<Serializable, Serializable> map = new HashMap<>(4);
            map.put(SHEET_NAME, "课程信息");
            map.put(CLASS, CourseExportTemplate.class);
            List<CourseExportTemplate> courseImportList = ExcelUtil.importExcel(Objects.requireNonNull(fileName), map, request, response);
            if (StringUtils.isEmpty(courseImportList)) {
                return ItooResult.build(ItooResult.FAIL, "导入的数据为空");
            }
            // 定义导入错误数据集合
            List<CourseExportTemplate> errorCourseList = new ArrayList<>();
            String errorListId = BaseUuidUtils.base58Uuid();
            Long size = redisTemplate.opsForZSet().size(errorListId);
            size = size == null ? 0L : size;
            // 循环处理数据
            for (CourseExportTemplate excelCourse : courseImportList) {
                // 数据验证
                if (!this.verify(excelCourse)) {
                    CourseExportTemplate courseExportTemplate = new CourseExportTemplate();
                    BeanUtils.copyProperties(excelCourse, courseExportTemplate);
                    errorCourseList.add(courseExportTemplate);
                    redisTemplate.opsForZSet().add(errorListId, courseExportTemplate, size + 1);
                    continue;
                }
                // 获取学院id
                String academyId = this.getAcademyId(excelCourse.getAcademyName());
                if (academyId == null){
                    academyId = "";
                }
                excelCourse.setAcademyId(academyId);
                // 课程类型等文字转数字
                excelCourse = this.convertToInt(excelCourse);
                //  数据复制给实体以添加
                CourseEntity courseEntity = new CourseEntity();
                BeanUtils.copyProperties(excelCourse, courseEntity);

                // 添加课程信息
                this.save(courseEntity);
            }
            // 不符合条件的信息返回
            if (errorCourseList.size() > 0) {
                return ItooResult.build("0001", "部分课程信息导入失败", errorListId);
            }
        } catch (Exception e) {
            return ItooResult.build(ItooResult.FAIL, "课程信息导入异常");
        }
        return ItooResult.build(ItooResult.SUCCESS, "课程信息导入成功");
    }

    /**
     * 根据学院名称获取学院ID-导入用
     *
     * @param academyName 学院id
     * @return 学院id
     * @author 张家豪
     * @since 2018.11.25 09:27
     */
    private String getAcademyId(String academyName) {
        return courseDao.getAcademyIdByName(academyName);
    }

    /**
     * 批量导入前验证数据是否符合要求
     *
     * @param courseExportTemplate 需要验证的数据
     * @return courseExportTemplate
     * @author 张家豪
     * @since 2018.11.25 08:59
     */
    private boolean verify(CourseExportTemplate courseExportTemplate) {
        // 判断非空字段是否有值
        if (StringUtils.isEmpty(courseExportTemplate.getCode())) {
            courseExportTemplate.setFailReason("课程编号未填写");
            log.warn("导入失败，code未填写，导入信息-", courseExportTemplate);
            return false;
        }
        if (StringUtils.isEmpty(courseExportTemplate.getName())) {
            courseExportTemplate.setFailReason("课程名称未填写");
            log.warn("导入失败，name未填写，导入信息-", courseExportTemplate);
            return false;
        }
        // 判断课程编号是否重复
        String courseCode = courseExportTemplate.getCode();
        if (this.findByCode(courseCode).size() > 0) {
            courseExportTemplate.setFailReason("课程编号已存在");
            log.warn("导入失败，code已存在，导入信息-", courseExportTemplate);
            return false;
        }
        return true;
    }


    /**
     * 课程类型等字段的文字转为数字-导入用
     *
     * @param courseExportTemplate 需要转换的数据
     * @return courseExportTemplate
     * @author 张家豪
     * @since 2018.11.25 11:50
     */
    private CourseExportTemplate convertToInt(CourseExportTemplate courseExportTemplate) {
        //1、1课程类别转换
        Map<String, String> courseCategoryMap = new HashMap<>();
        courseCategoryMap.put("理论课", "1");
        courseCategoryMap.put("实践课", "2");
        courseCategoryMap.put("理论实践课", "3");
        //1、2课程类型转换
        Map<String, String> courseTypeMap = new HashMap<>();
        courseTypeMap.put("专业必修", "1");
        courseTypeMap.put("公共必修", "2");
        courseTypeMap.put("专业选修", "3");
        courseTypeMap.put("公共选修", "4");
        //1、3课程性质转换
        Map<String, String> courseNatureMap = new HashMap<>();
        courseNatureMap.put("人文社科", "1");
        courseNatureMap.put("艺术体育", "2");
        courseNatureMap.put("自然科学", "3");

        // 2转换
        courseExportTemplate.setCourseCategory(courseCategoryMap.get(courseExportTemplate.getCourseCategoryName()));
        courseExportTemplate.setCourseType(courseTypeMap.get(courseExportTemplate.getCourseTypeName()));
        courseExportTemplate.setCourseNature(courseNatureMap.get(courseExportTemplate.getCourseNatureName()));

        return courseExportTemplate;
    }

    /**
     * 根据课程名称查询课程信息
     *
     * @param name 课程名称
     * @return courseentity
     * @author 张家豪
     * @since 2018.11.28 14:38
     */
    @Override
    public List<CourseEntity> findCourseByName(String name) {
        return courseDao.findCourseByName(name);
    }


    @Override
    public boolean downErrorList(String errorListId, HttpServletResponse response) {
        // redis 取出没有成功导入的人员信息
        Set set = redisTemplate.opsForZSet().range(errorListId, 0, -1);
        List<CourseExportTemplate> courseExportTemplates = new ArrayList<>(set);
        // 清空redis数据
        redisTemplate.delete(errorListId);

        //导出
        if (courseExportTemplates.size() == 0) {
            return false;
        }
        Map<Serializable, Serializable> errorMap = new HashMap<>(16);
        errorMap.put(NAME, "未导入的信息");
        errorMap.put(SHEET_NAME, "课程信息");
        errorMap.put(TITLE, "未导入的信息");
        errorMap.put(COLUMNS, new String[]{"code", "name", "courseCategoryName", "courseTypeName", "courseNatureName", "academyName", "classHour", "classPoint", "score","failReason"});
        errorMap.put(DATA_LIST, (Serializable) courseExportTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 根据学院ID查询所有课程
     *
     * @param academyId 学院id
     * @return courseModel
     * @author 宋喆
     * @since 2018.12.14 20:05
     */
    @Override
    public List<CourseModel> queryCourseByacademyId(String academyId) {
        return courseDao.queryCourseByacademyId(academyId);
    }

    /**
     * 根据课程id查询课程名称
     *
     * @return 当前学年课程信息
     * @author 杨江涛
     * @since 2.0.0 2018-11-24 15:14:12
     */
    @Override
    public CourseEntity findCourse(String id) {
        return courseDao.findCourse(id);
    }

    /**
     * 根据参数模糊查询课程名称返回list类型
     * @param searchInfo 模糊查询条件（课程名称/课程代码）searchInfo
     * @return 根据参数模糊查询课程名称返回list类型
     * @author 杨江涛
     * @since 2.0.0  2018-12-6 14:50:58
     */
    @Override
    public PageInfo<CourseEntity> getCourse(String searchInfo, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        return new PageInfo<>(courseDao.getCourse(searchInfo));
    }

    /**
     * 创建考试查询课程,无参查询
     *
     * @param userId userId
     * @author maying
     * @since 2018-12-8 21:42:00
     */
    @Override
    public List<CourseEntity> inquiryCourse(String semester, String userId) {

        List<CourseEntity> courseList = courseDao.inquiryCourse(semester,userId);
        return courseList;
    }

    /**
     * 课程练习-查询所有属于课程练习的课程
     *
     * @return 是否查询成功
     * @author 贾建清
     * @since 2.0.0 2019-3-24 09:51:24
     */
    @Override
    public List<CourseEntity> queryCourseAll() {
        List<CourseEntity> courseEntityList = courseDao.queryCourseAll();
        return courseEntityList;
    }


}
